package com.ls.stack;

import lombok.Data;

import java.util.Objects;

/**
 * @program: dataStructure
 * @author: lishun
 * @create: 2021-12-05 21:15
 **/
@Data
//todo 不支持括号()
public class Calculator {
    private LinkStack<Integer> numStack = new LinkStack<>();
    private LinkStack<Character> symbolStack = new LinkStack<>();

    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        int i = calculator.expressionCal("2+100-2+2/2+1*40");
        System.out.println(i);
    }

    /**
     * 表达式计算
     */
    public int expressionCal(String expression){
        if (Objects.isNull(expression) || expression.isEmpty()){
            throw new RuntimeException("表达式不正确");
        }
        // 帮助遍历表达式的索引
        int index = 0;
        int length = expression.length();
        while (index<length){
            char value = expression.charAt(index);
            if (priority(value)!=-1){
                // 符号分两种情况
                if (!this.symbolStack.isEmpty()){
                    // 比较优先级
                    if (priority(value)<=priority(this.symbolStack.getTop().getData())){
                        //优先级小于于等于栈顶符号
                        // 弹出两个数进行计算
                        Integer num1 = this.numStack.pop();
                        Integer num2 = this.numStack.pop();
                        Character symbol = this.symbolStack.pop();
                        this.numStack.push(this.calculate(num1,num2,symbol));
                        this.symbolStack.push(value);
                    }else {
                        this.symbolStack.push(value);
                    }
                } else {
                    // 为空直接入栈
                    this.symbolStack.push(value);
                }

            }else {
                // 数字入栈(不能直接入栈，可能后面还是一个数子，如果后面是个数字，就拼接一个数字才能入栈)
                // 判断下一个是不是数字
                int temp = index;
                StringBuilder builder = new StringBuilder();
                builder.append(value);
                while (true){
                    // 查看后面一位前要判断后一位是否越界
                    if (++temp<length && this.priority(expression.charAt(temp)) ==-1 ){
                        index++;
                        builder.append(expression.charAt(temp));
                    }else {
                        break;
                    }
                }
                this.numStack.push(Integer.valueOf(builder.toString()));
            }
            index++;
        }
        while (true){
            if (this.symbolStack.isEmpty()){
                break;
            }
            Integer num1 = this.numStack.pop();
            Integer num2 = this.numStack.pop();
            Character symbol = this.symbolStack.pop();
            this.numStack.push(this.calculate(num1,num2,symbol));
        }
        return this.numStack.pop();
    }

    /**
     * 运算符优先级
     * @param oper
     * @return
     */
    public int priority(char oper){
        if (oper =='*' || oper == '/' ){
            return 1;
        }else if (oper == '+' || oper == '-'){
            return 0;
        }else {
            return -1;
        }
    }
    /**
     *  计算
     */
    public int calculate(int num1,int num2,char oper){
        // 校验符号
        if (priority(oper)==-1){
            throw new RuntimeException("符号不支持");
        }
        int result = 0;
        switch (oper){
            case '*':
                result = num1 * num2;
                break;
            case '/':
                result = num2 / num1;
                break;
            case '+':
                result = num1 + num2;
                break;
            case  '-':
                result = num2 - num1;
                break;
        }
        return result;
    }

}
